#include "signals.h"
#include <iostream>

namespace anet {
	namespace utils {
		std::condition_variable CSignal::m_cv;
		std::mutex CSignal::m_mtx;
		bool CSignal::m_stopRequested = false;

		CSignal::CSignal() {
#ifdef _WIN32
			// for windows
			if (!SetConsoleCtrlHandler(ConsoleHandler, TRUE)) {
				std::cerr << "Error: Unable to set console handler.\n";
				throw "register signal error";
			}
#else
			// for linux like.
			std::signal(SIGINT, CSignal::signalHandler);
			std::signal(SIGTERM, CSignal::signalHandler);
#endif
		}

		// for linux like.
#ifndef _WIN32
		void CSignal::signalHandler(int signal) {
			if (signal == SIGINT || signal == SIGTERM) {
				requestStop();
			}
		}
#endif

		// for windows.
#ifdef _WIN32
		BOOL WINAPI CSignal::ConsoleHandler(DWORD signal) {
			if (signal == CTRL_C_EVENT || signal == CTRL_CLOSE_EVENT ||
				signal == CTRL_BREAK_EVENT || signal == CTRL_LOGOFF_EVENT ||
				signal == CTRL_SHUTDOWN_EVENT) {
				requestStop();
				return TRUE;
			}
			return FALSE;
		}
#endif

		void CSignal::requestStop() {
			std::lock_guard<std::mutex> lock(m_mtx);
			m_stopRequested = true;
			m_cv.notify_all();
		}

		bool CSignal::isSignaled() {
			return m_stopRequested;
		}
	}
}